#pragma once

#include <iostream>
#include <fstream>
#include <cstdio>
#include <string>
#include <ctime>
#include <cstdarg>
#include <sys/types.h>
#include <unistd.h>
#include <pthread.h>
#include "Lockgarud.hpp"
bool gIsSave = false;
const std::string logname = "log.txt";

// 日志等级
enum Level
{
	DEBUG = 0,
	INFO,
	WARNING,
	ERROR,
	FATAL
};

std::string LevelToStr(int level)
{
	switch (level)
	{
	case DEBUG:
		return "DEBUG";
	case INFO:
		return "INFO";
	case WARNING:
		return "WARNING";
	case ERROR:
		return "ERROR";
	case FATAL:
		return "FATAL";
	default:
		return "Unknown";
	}
}

std::string GetTimeStr()
{
	time_t curr_time = time(nullptr);
	struct tm *format_time = localtime(&curr_time);
	if (format_time == nullptr)
	{
		return "none";
	}

	char time_buffer[1024];
	snprintf(time_buffer, sizeof(time_buffer), "%d-%d-%d-%d-%d-%d",
			 format_time->tm_year + 1900,
			 format_time->tm_mon + 1,
			 format_time->tm_yday,
			 format_time->tm_hour,
			 format_time->tm_min,
			 format_time->tm_sec);

	return time_buffer;
}

void SaveFile(const std::string &filename, const std::string &message)
{
	std::ofstream out(filename, std::ios::app);
	if (!out.is_open())
	{
		return;
	}

	out << message;
	out.close();
}

pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;

// 2. 日志是由格式的
// 日志等级 时间 代码所在的文件名/行数 日志的内容
void LogMessage(std::string filename, int line, bool issave, int level, const char *format, ...)
{
	std::string levelstr = LevelToStr(level);
	std::string timestr = GetTimeStr();
	pid_t selfid = getpid();

	char buffer[1024];
	va_list arg;
	va_start(arg, format);
	vsnprintf(buffer, sizeof(buffer), format, arg);
	va_end(arg);

	std::string message = "[" + timestr + "]" + "[" + levelstr + "]" +
						  "[" + std::to_string(selfid) + "]" +
						  "[" + filename + "]" + "[" + std::to_string(line) + "] " + buffer;

	LockGuard Lockguag(&lock);
	if (!issave)
	{
		std::cout << message << std::endl;
	}
	else
	{
		SaveFile(logname, message);
	}
}

// C99新特性__VA_ARGS__
// ##__VA_ARGS__，解决后面没带参的行为
#define LOG(level, format, ...)                                                \
	do                                                                         \
	{                                                                          \
		LogMessage(__FILE__, __LINE__, gIsSave, level, format, ##__VA_ARGS__); \
	} while (0)

#define EnableFile() do{gIsSave = true;}while(0)


#define EnableScreen() do{gIsSave = false;}while(0)

